"""
Main entry point for the Smart Mesh Optimizer
"""
import os
import sys
import time

from src.core.mesh_io import MeshIO
from src.core.mesh_quality import MeshQuality
from src.core.mesh_optimizer import MeshOptimizer
from src.utils.visualization import MeshVisualizer
from src.utils.logger import Logger
from src.utils.cli_helpers import (
    create_parser, validate_args, print_header,
    print_mesh_stats, print_quality_metrics, print_optimization_results
)

def analyze_command(args, logger):
    """
    Execute the analyze command
    
    Parameters:
    -----------
    args : argparse.Namespace
        Command-line arguments
    logger : Logger
        Logger instance
    """
    logger.info(f"Analyzing mesh: {args.input}")
    
    # Read mesh
    try:
        mesh_data = MeshIO.read_mesh(args.input)
        logger.log_mesh_stats(mesh_data)
        print_mesh_stats(mesh_data)
    except Exception as e:
        logger.error(f"Error reading mesh: {e}")
        print(f"Error reading mesh: {e}")
        return
    
    # Calculate quality metrics
    try:
        quality_metrics = MeshQuality.calculate_quality_metrics(mesh_data)
        logger.log_quality_metrics(quality_metrics)
        print_quality_metrics(quality_metrics)
    except Exception as e:
        logger.error(f"Error calculating quality metrics: {e}")
        print(f"Error calculating quality metrics: {e}")
        return
    
    # Identify poor quality elements
    try:
        poor_elements = MeshQuality.identify_poor_quality_elements(mesh_data)
        logger.info(f"Number of poor quality elements: {len(poor_elements)}")
        print(f"\nNumber of poor quality elements: {len(poor_elements)}")
    except Exception as e:
        logger.error(f"Error identifying poor quality elements: {e}")
        print(f"Error identifying poor quality elements: {e}")
    
    # Visualize if requested
    if args.visualize:
        try:
            # Plot mesh
            MeshVisualizer.plot_mesh(mesh_data, title=f"Mesh: {os.path.basename(args.input)}")
            
            # Plot quality histogram
            MeshVisualizer.plot_quality_histogram(
                quality_metrics, 
                title=f"Quality Histogram: {os.path.basename(args.input)}",
                save_path=args.save_plot
            )
        except Exception as e:
            logger.error(f"Error visualizing mesh: {e}")
            print(f"Error visualizing mesh: {e}")

def optimize_command(args, logger):
    """
    Execute the optimize command
    
    Parameters:
    -----------
    args : argparse.Namespace
        Command-line arguments
    logger : Logger
        Logger instance
    """
    logger.info(f"Optimizing mesh: {args.input}")
    logger.info(f"Method: {args.method}, Iterations: {args.iterations}, Threshold: {args.threshold}")
    
    # Read mesh
    try:
        mesh_data = MeshIO.read_mesh(args.input)
        logger.log_mesh_stats(mesh_data, "Original ")
        print_mesh_stats(mesh_data)
    except Exception as e:
        logger.error(f"Error reading mesh: {e}")
        print(f"Error reading mesh: {e}")
        return
    
    # Calculate quality metrics
    try:
        quality_metrics = MeshQuality.calculate_quality_metrics(mesh_data)
        logger.log_quality_metrics(quality_metrics, "Original ")
        print_quality_metrics(quality_metrics)
    except Exception as e:
        logger.error(f"Error calculating quality metrics: {e}")
        print(f"Error calculating quality metrics: {e}")
        return
    
    # Optimize mesh
    try:
        print(f"\nOptimizing mesh using {args.method} method...")
        start_time = time.time()
        
        optimizer = MeshOptimizer(mesh_data)
        optimization_results = optimizer.optimize(
            method=args.method,
            iterations=args.iterations,
            quality_threshold=args.threshold
        )
        
        end_time = time.time()
        elapsed_time = end_time - start_time
        
        logger.info(f"Optimization completed in {elapsed_time:.2f} seconds")
        logger.log_optimization_results(optimization_results)
        print(f"Optimization completed in {elapsed_time:.2f} seconds")
        print_optimization_results(optimization_results)
    except Exception as e:
        logger.error(f"Error optimizing mesh: {e}")
        print(f"Error optimizing mesh: {e}")
        return
    
    # Write optimized mesh
    try:
        optimized_mesh = optimization_results['mesh_data']
        MeshIO.write_mesh(optimized_mesh, args.output)
        logger.info(f"Optimized mesh saved to: {args.output}")
        print(f"\nOptimized mesh saved to: {args.output}")
    except Exception as e:
        logger.error(f"Error writing optimized mesh: {e}")
        print(f"Error writing optimized mesh: {e}")
    
    # Visualize if requested
    if args.visualize:
        try:
            # Plot quality comparison
            MeshVisualizer.plot_quality_comparison(
                quality_metrics,
                optimization_results['quality_metrics'],
                title=f"Quality Comparison: {os.path.basename(args.input)}",
                save_path=args.save_plot
            )
        except Exception as e:
            logger.error(f"Error visualizing quality comparison: {e}")
            print(f"Error visualizing quality comparison: {e}")

def visualize_command(args, logger):
    """
    Execute the visualize command
    
    Parameters:
    -----------
    args : argparse.Namespace
        Command-line arguments
    logger : Logger
        Logger instance
    """
    logger.info(f"Visualizing mesh: {args.input}")
    
    # Read mesh
    try:
        mesh_data = MeshIO.read_mesh(args.input)
        logger.log_mesh_stats(mesh_data)
        print_mesh_stats(mesh_data)
    except Exception as e:
        logger.error(f"Error reading mesh: {e}")
        print(f"Error reading mesh: {e}")
        return
    
    # Visualize mesh
    try:
        if args.quality:
            # Calculate quality metrics
            quality_metrics = MeshQuality.calculate_quality_metrics(mesh_data)
            logger.log_quality_metrics(quality_metrics)
            print_quality_metrics(quality_metrics)
            
            # Visualize quality
            quality_values = quality_metrics['quality_values']
            MeshVisualizer.visualize_quality_vtk(
                mesh_data, 
                quality_values=quality_values,
                title=f"Mesh Quality: {os.path.basename(args.input)}"
            )
        else:
            # Visualize mesh
            MeshVisualizer.plot_mesh(
                mesh_data, 
                title=f"Mesh: {os.path.basename(args.input)}",
                save_path=args.save_plot
            )
    except Exception as e:
        logger.error(f"Error visualizing mesh: {e}")
        print(f"Error visualizing mesh: {e}")

def compare_command(args, logger):
    """
    Execute the compare command
    
    Parameters:
    -----------
    args : argparse.Namespace
        Command-line arguments
    logger : Logger
        Logger instance
    """
    logger.info(f"Comparing meshes: {args.original} and {args.optimized}")
    
    # Read original mesh
    try:
        original_mesh = MeshIO.read_mesh(args.original)
        logger.log_mesh_stats(original_mesh, "Original ")
        print_mesh_stats(original_mesh)
    except Exception as e:
        logger.error(f"Error reading original mesh: {e}")
        print(f"Error reading original mesh: {e}")
        return
    
    # Read optimized mesh
    try:
        optimized_mesh = MeshIO.read_mesh(args.optimized)
        logger.log_mesh_stats(optimized_mesh, "Optimized ")
        print_mesh_stats(optimized_mesh)
    except Exception as e:
        logger.error(f"Error reading optimized mesh: {e}")
        print(f"Error reading optimized mesh: {e}")
        return
    
    # Calculate quality metrics
    try:
        original_metrics = MeshQuality.calculate_quality_metrics(original_mesh)
        logger.log_quality_metrics(original_metrics, "Original ")
        print_quality_metrics(original_metrics)
        
        optimized_metrics = MeshQuality.calculate_quality_metrics(optimized_mesh)
        logger.log_quality_metrics(optimized_metrics, "Optimized ")
        print_quality_metrics(optimized_metrics)
    except Exception as e:
        logger.error(f"Error calculating quality metrics: {e}")
        print(f"Error calculating quality metrics: {e}")
        return
    
    # Calculate improvement
    improvement_percentage = (
        (original_metrics['avg_quality'] - optimized_metrics['avg_quality']) / 
        original_metrics['avg_quality'] * 100
    ) if original_metrics['avg_quality'] > 0 else 0
    
    logger.info(f"Improvement percentage: {improvement_percentage:.2f}%")
    print(f"\nImprovement percentage: {improvement_percentage:.2f}%")
    
    # Visualize if requested
    if args.visualize:
        try:
            # Plot quality comparison
            MeshVisualizer.plot_quality_comparison(
                original_metrics,
                optimized_metrics,
                title="Quality Comparison",
                save_path=args.save_plot
            )
        except Exception as e:
            logger.error(f"Error visualizing quality comparison: {e}")
            print(f"Error visualizing quality comparison: {e}")

def main():
    """Main entry point"""
    # Create parser and parse arguments
    parser = create_parser()
    args = parser.parse_args()
    
    # Print header
    print_header()
    
    # Create logger
    logger = Logger()
    
    # Validate arguments
    if not validate_args(args):
        parser.print_help()
        return 1
    
    # Execute command
    try:
        if args.command == 'analyze':
            analyze_command(args, logger)
        elif args.command == 'optimize':
            optimize_command(args, logger)
        elif args.command == 'visualize':
            visualize_command(args, logger)
        elif args.command == 'compare':
            compare_command(args, logger)
        else:
            print(f"Unknown command: {args.command}")
            parser.print_help()
            return 1
    except Exception as e:
        logger.error(f"Error executing command: {e}")
        print(f"Error executing command: {e}")
        return 1
    
    return 0

if __name__ == "__main__":
    sys.exit(main()) 